﻿using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TomShane.Neoforce.Controls;

namespace SpaceInvade.Ships
{
    // Base Ship class
    public enum shipDirection
    {
        Horizontal,
        Vertical
    };

    public class Ship
    {
        protected double LastFire;
        
        public Ship()
        {
        }
        // Create ship
        public void CreateShip(String Mode, Manager _Manager, int startX, int startY, Color tint)
        {
        }

        // Draw ship
        public virtual void Draw(SpriteBatch spritebatch)
        {
        }

        // Shoot
        public virtual void ShootBullet(ref List<Bullet> bullets)
        {
        }

        // Move Ship
        public virtual bool Move(Manager manager,String Direction)
        {
            return false;
        }

        public virtual bool CheckCollision(Bullet bullet)
        {
            return false;
        }

        // Am I dead
        public virtual bool IsDead()
        {
            return false;
        }
    }

    // Player Ship Class
    class PlayerShip : Ship
    {
        // Create ship properties
        int shipWidth = 32;
        int shipHeight = 32;
        int healthbarVerticalOffset = 8;
        int healthbarHeight = 5;
        int Padding = 8;
        int MovementSpeed = 5; // Measured in Pixels
        shipDirection Movement = shipDirection.Horizontal;
        Rectangle Location;
        bulletType btype = bulletType.Bullet1;
        int ShotRate = 25;
        float ShotSleep;
        public int deathState = 0;
        float MaxHealth;
        float CurrentHealth;
        String Mode;
        Texture2D spriteSheet;
        String DrawDirection = "Up";
        // Keyboard assignments
        Keys Right;
        Keys Left;
        Keys Up;
        Keys Down;
        Keys Shoot;
        Color playerColor = Color.Gray;
        Rectangle SrcRectangle = new Rectangle(0, 0, 32, 32);
        Ships.HealthBar healthBar;
		Explode Explode;
        Manager manager;

        // Create ship
        // Mode=Should ship be limited to the bottom horizontal plane
        // Content=Content manager to facilitate loading of textures (maybe should create a separate Load method)
        // startX and startY are the top-left corner of this ship. The ship will know it's Height and Width
        // Color=Color tint to apply to the ship, used for identifying individual players
            // Key assignments for player movement passed in (need to add "fire" button once bullets are done)
        public PlayerShip(String _Mode, Manager _Manager, int _StartX, int _StartY, Color _Color, 
           PlayerInfo PI)
        {
            manager = _Manager;
            LastFire = Game1.Time.TotalGameTime.Seconds;
            //Game1.content.RootDirectory = "Content";
            spriteSheet = PI.ShipIcon;//_Content.Load<Texture2D>(@"Textures\playerShip2");
            Location = new Rectangle(_StartX, _StartY, shipWidth, shipHeight);
            playerColor = _Color;
            MaxHealth = 100;
            CurrentHealth = 100;
            Right = PI.ControlKeys[1];
            Left = PI.ControlKeys[0];
            Up = PI.ControlKeys[2];
            Down = PI.ControlKeys[3];
            Shoot = PI.ControlKeys[4];
            Mode = _Mode;
            // Create the healthbar for the ship
            healthBar = new HealthBar(new Rectangle(Location.X, Location.Y - healthbarVerticalOffset, shipWidth, healthbarHeight), 
                true, Color.SlateGray, Color.Green, CurrentHealth, MaxHealth);
				            // For simplicity sake I'm creating the Explode object now but we should probably
                // pass the manager class to the update class so the explode class doesn't sit in memory if it doesn't have to.
            // Create Explode instance
            Explode = new Explode(_Manager.Content);
        }

        // Handle Ship Movement
        public override bool Move(Manager _Manager, String Direction)
        {
            // Can't move when you're dead
            if (deathState == 0)
            {
                // If currently in Horizontal movement, check for position at outside edge and allow changing to Vertical
                if (Mode == "Free")
                {
                    if (Movement == shipDirection.Horizontal && (Location.X == Padding ||
                        Location.X == _Manager.GraphicsDevice.Viewport.Bounds.Width - (Location.Width + Padding)))
                    {
                        if (Keyboard.GetState().IsKeyDown(Up) || Keyboard.GetState().IsKeyDown(Down))
                        {
                            Movement = shipDirection.Vertical;
                        }
                    }
                    else if (Movement == shipDirection.Vertical && (Location.Y == Padding ||
                        Location.Y == _Manager.GraphicsDevice.Viewport.Bounds.Height - (Location.Height + Padding)))
                    {
                        if (Keyboard.GetState().IsKeyDown(Left) || Keyboard.GetState().IsKeyDown(Right))
                        {
                            Movement = shipDirection.Horizontal;
                        }
                    }
                }

                // handling keyboard inputs
                if (Movement == shipDirection.Horizontal)
                {
                    if (Keyboard.GetState().IsKeyDown(Left)) // Left key down ?
                        Location.X -= MovementSpeed; // move the player
                    else if (Keyboard.GetState().IsKeyDown(Right)) // Right key down ?
                        Location.X += MovementSpeed; // move the player

                    // Set the graphic rotation direction for the ship (used in the draw method)
                    if (Location.Y > _Manager.GraphicsDevice.Viewport.Bounds.Height / 2)
                        DrawDirection = "Up";
                    else
                        DrawDirection = "Down";
                }
                else if (Movement == shipDirection.Vertical)
                {
                    if (Keyboard.GetState().IsKeyDown(Up)) // Left key down ?
                        Location.Y -= MovementSpeed; // move the player
                    else if (Keyboard.GetState().IsKeyDown(Down)) // Right key down ?
                        Location.Y += MovementSpeed; // move the player
                    // Set the graphic rotation direction for the ship (used in the draw method)
                    if (Location.X > _Manager.GraphicsDevice.Viewport.Bounds.Width / 2)
                        DrawDirection = "Left";
                    else
                        DrawDirection = "Right";
                }
			}

            // limit the player's horizontal movement to the screen bounds
            if (Location.X < (0 + Padding)) // Left bound
            {
                Location.X = (0 + Padding);
            }
            else if (Location.X + Location.Width + Padding > _Manager.GraphicsDevice.Viewport.Bounds.Width) // Right bound
            {
                Location.X = _Manager.GraphicsDevice.Viewport.Bounds.Width - Padding - Location.Width;
            }

            // Limit the player's Vertical movement to the screen bounds
            if (Location.Y < (0 + Padding)) // Left bound
            {
                Location.Y = (0 + Padding);
            }
            else if (Location.Y + Location.Width + Padding > _Manager.GraphicsDevice.Viewport.Bounds.Height) // Right bound
            {
                Location.Y = _Manager.GraphicsDevice.Viewport.Bounds.Height - Padding - Location.Height;
            }
            // Update the healthbar before drawing
            //CurrentHealth = (CurrentHealth - .2f);
            healthBar.setCurrentHealth(CurrentHealth);
			healthBar.TrackShip(Location.X, Location.Y - 10);
            if (CurrentHealth <= 0)
                deathState = Explode.CheckFinished(Location);
            
            // Enemy ships communicate direction changes using a return bool. 
            // Player should always return false because it's not involved in enemy direction changes (yet...)
            return false;
        }

        // Shoot
        public override void ShootBullet(ref List<Bullet> bullets)
        {
            //if (timer has been long enough)
            double Difference = Game1.Time.TotalGameTime.TotalMilliseconds - LastFire;
            if (Difference > 300 && Keyboard.GetState().IsKeyDown(Shoot)) // Shoot key down
            {
                ShotSleep = 1000f / (float)ShotRate;
                int BulletAngle = 0;
                // Start X, Start Y, Percent X speed, Percent Y Speed;
                Vector4 bulletInitPosAndSpeed = new Vector4();
                switch (DrawDirection)
                {
                    case "Up":
                        bulletInitPosAndSpeed = new Vector4((Location.X+Location.Width/2),Location.Y, 0f, -.75f);
                        BulletAngle = 0;
                        break;
                    case "Down":
                        bulletInitPosAndSpeed = new Vector4((Location.X+Location.Width/2),(Location.Y + Location.Height), 0f, .75f);
                        BulletAngle = 0;
                        break;
                    case "Left":
                        bulletInitPosAndSpeed = new Vector4((Location.X),(Location.Y+Location.Height/2), -.75f, 0f);
                        BulletAngle = 0;
                        break;
                    case "Right":
                        bulletInitPosAndSpeed = new Vector4((Location.X+Location.Width),(Location.Y+Location.Height/2), .75f, 0f);
                        BulletAngle = 0;
                        break;
                }
                bullets.Add(new Bullet(manager, btype, bulletInitPosAndSpeed, 1f, this, BulletAngle));
                LastFire = Game1.Time.TotalGameTime.TotalMilliseconds;
            }

            FreeMode.lblDisposable.Text = Game1.Time.TotalGameTime.TotalMilliseconds.ToString();
            //}
        }

        // Draw ship
        public override void Draw(SpriteBatch spritebatch)
        {
            //Rectangle temp = new Rectangle(0, 0, 32, 32);
            float baseturn = 1.5655f;
            float turn = 0;
            // Get correct rotation for graphic
            if (DrawDirection == "UP")
                turn = 0;
            else if (DrawDirection == "Right")
                turn = baseturn * 1;
            else if (DrawDirection == "Down")
                turn = baseturn * 2;
            else if (DrawDirection == "Left")
                turn = baseturn * 3;

            // Per-draw Rectangle and Vecotor to facilitate rotation
            Rectangle DrawnLocation = new Rectangle(
                Location.X + (Location.Width / 2),
                        Location.Y + (Location.Height / 2),
                        Location.Height,
                        Location.Width);
            Vector2 DrawnPivot = new Vector2(Location.Width / 2,
                Location.Height / 2);
            // Draw ship on screen
            spritebatch.Draw(spriteSheet,
                    DrawnLocation,
                    null,
                    playerColor,
                    turn,
                    DrawnPivot,
                    SpriteEffects.None, 1);
            // Draw ship healthbar
            healthBar.Draw(spritebatch);
			if (deathState != 0)
                Explode.Draw(spritebatch, DrawnLocation);
        }
        // Am I dead
        public override bool IsDead()
        {
            if (deathState == 3)
                return true;
            else
                return false;
        }
    }


    // Enemy1 Ship Class
    class EnemyShip1 : Ship
    {
        // Create ship properties
        int shipWidth = 32;
        int shipHeight = 32;
        int healthbarVerticalOffset = 8;
        int healthbarHeight = 5;
        int Padding = 16;
        int MovementSpeed = 2;
        Rectangle Location;
        bulletType btype = bulletType.Bullet2;
        int ShotRate;
        public int deathState = 0;
        String Direction = "Right";
        float MaxHealth;
        float CurrentHealth;
        Texture2D spriteSheet;
        Color playerColor = Color.Gray;
        Rectangle SrcRectangle = new Rectangle(0, 0, 32, 32);
        Ships.HealthBar healthbar;
        Explode Explode;

        // Create ship
        public EnemyShip1(Manager _Manager, int startX, int startY, Color tint)
        {
            // content.RootDirectory = "SpaceInvadersContent";
            spriteSheet = _Manager.Content.Load<Texture2D>(@"Textures\enemy1");
            Location = new Rectangle(startX, startY, shipWidth, shipHeight);
            playerColor = tint;
            MaxHealth = 100;
            CurrentHealth = 100;
            ShotRate = 25;
            healthbar = new HealthBar(new Rectangle(Location.X, Location.Y - healthbarVerticalOffset, shipWidth, healthbarHeight),
    true, Color.SlateGray, Color.Green, CurrentHealth, MaxHealth);
            Explode = new Explode(_Manager.Content);
        }

        // Draw ship
        public override void Draw(SpriteBatch spritebatch)
        {
            // Per-draw Rectangle and Vecotor to facilitate rotation
            Rectangle DrawnLocation = new Rectangle(
                Location.X + (Location.Width / 2),
                        Location.Y + (Location.Height / 2),
                        Location.Height,
                        Location.Width);
            // Draw ship
            spritebatch.Draw(spriteSheet, Location, playerColor);
            // Draw ship healthbar
            healthbar.Draw(spritebatch);
            if (deathState != 0)
                Explode.Draw(spritebatch, DrawnLocation);
        }

        // Shoot
        public override void ShootBullet(ref List<Bullet> bullets)
        {
        }

        // Move Ship
        public override bool Move(Manager _Manager,String Direction)
        {
            bool ChangeDirection = false;
            if (deathState == 0)
            {
                // Move ship from side to side
                if (Direction == "Right")
                {
                    this.Location.X += MovementSpeed;
                }
                else if (Direction == "Left")
                {
                    this.Location.X -= MovementSpeed;
                }

                // Bounce box from screen edge to screen edge with a 64px padding (will need to check game state to determine padding level)
                if (Direction == "Left")
                {
                    if ((this.Location.X - MovementSpeed) < Padding)
                        ChangeDirection = true;
                }
                else if (Direction == "Right")
                {
                    if ((this.Location.X + this.Location.Width + MovementSpeed) > (_Manager.GraphicsDevice.Viewport.Bounds.Width - Padding))
                        ChangeDirection = true;
                }
            }
            healthbar.setCurrentHealth(CurrentHealth);
            healthbar.TrackShip(Location.X, Location.Y - 10);
            if (CurrentHealth <= 0)
                deathState = Explode.CheckFinished(Location);
            return ChangeDirection;
        }

        public override bool CheckCollision(Bullet bullet)
        {
            Rectangle bulBoarder = bullet.Location;
            Rectangle shipBoarder = this.Location;

            if (bulBoarder.Y < shipBoarder.Y + shipBoarder.Height && bulBoarder.Y > shipBoarder.Y)
            {
                if (bulBoarder.X < shipBoarder.X + shipBoarder.Width && bulBoarder.X > shipBoarder.X)
                {
                    CurrentHealth -= bullet.DamageValue;
                    return true;
                }
            }

            return false;
        }

        // Am I dead
        public override bool IsDead()
        {
            if (deathState == 3)
                return true;
            else
                return false;
        }
    }
}
